package com.chanel.iamframework.core.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.validation.constraints.NotNull;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.chanel.iamframework.core.dao.GroupDAO;
import com.chanel.iamframework.core.domain.Application;
import com.chanel.iamframework.core.domain.Group;
import com.chanel.iamframework.core.domain.Role;
import com.chanel.iamframework.core.domain.User;
import com.chanel.iamframework.core.service.GroupService;

public class GroupServiceImpl implements GroupService {

	private static final Logger logger = LoggerFactory.getLogger(GroupServiceImpl.class);
	
	private GroupDAO groupDAO;

	public GroupServiceImpl(@NotNull GroupDAO groupDAO) {
		this.groupDAO = groupDAO;
	}
	
	@Override
	public Group getGroup(Long groupId) {
		return groupDAO.getGroup(groupId);
	}

	@Override
	public void createGroup(Group group) {
		groupDAO.createGroup(group);
	}

	@Override
	public boolean updateGroup(Group group) {
		return groupDAO.updateGroup(group) > 0 ? true : false;
	}

	@Override
	public boolean deleteGroup(Long groupId) {
		return groupDAO.deleteGroup(groupId) > 0 ? true : false;
	}

	@Override
	public Group loadRoles(Long groupId) {
		return groupDAO.loadRoles(groupId);
	}

	@Override
	public Group loadUsers(Long groupId) {
		return groupDAO.loadUsers(groupId);
	}

	@Override
	public Group loadApplications(Long groupId) {
		return groupDAO.loadApplications(groupId);
	}

	@Override
	public void addRoles(Group group) {
		if (CollectionUtils.isEmpty(group.getRoles())) {
			logger.debug("group.roles is empty");
		} else {
			logger.debug("group.roles contain {} roles", group.getRoles().size());
			
			for (Role role: group.getRoles()) {
				groupDAO.addRole(group.getGroupId(), role.getRoleId());
				logger.debug("association ({}, {}) created", group, role);
			}
		}
	}

	@Override
	public boolean deleteRoles(Group group) {
		boolean deletedRoles = false;
		
		if (CollectionUtils.isEmpty(group.getRoles())) {
			logger.debug("group.roles is empty");
		} else if (groupDAO.getGroup(group.getGroupId()) == null) {
			logger.debug("groupId={} not exist", group.getGroupId());
		} else {
			List<Role> rolesToBeDeleted = new ArrayList<Role>();
			
			logger.debug("group.roles contain {} roles", group.getRoles().size());
			for (Role role: group.getRoles()) {
				if (groupDAO.deleteRole(group.getGroupId(), role.getRoleId()) > 0) {
					rolesToBeDeleted.add(role);
					logger.debug("association ({}, {}) deleted", group, role);
				} else {
					logger.debug("association ({}, {}) not found", group, role);
				}
			}
			
			group.getRoles().removeAll(rolesToBeDeleted);
			deletedRoles = rolesToBeDeleted.size() > 0;
		}
		
		return deletedRoles;
	}

	@Override
	public void addApplications(Group group) {
		if (CollectionUtils.isEmpty(group.getApplications())) {
			logger.debug("group.applications is empty");
		} else {
			logger.debug("group.applications contain {} applications", group.getApplications().size());
			
			for (Application application: group.getApplications()) {
				groupDAO.addApplication(application.getApplicationId(), group.getGroupId());
				logger.debug("association ({}, {}) created", group, application);
			}
		}
	}

	@Override
	public boolean deleteApplications(Group group) {
		boolean deletedApplications = false;
		
		if (CollectionUtils.isEmpty(group.getApplications())) {
			logger.debug("group.applications is empty");
		} else if (groupDAO.getGroup(group.getGroupId()) == null) {
			logger.debug("groupId={} not exist", group.getGroupId());
		} else {
			List<Application> applicationsToBeDeleted = new ArrayList<Application>();
			
			logger.debug("group.applications contain {} applications", group.getApplications().size());
			for (Application application: group.getApplications()) {
				if (groupDAO.deleteApplication(application.getApplicationId(), group.getGroupId()) > 0) {
					applicationsToBeDeleted.add(application);
					logger.debug("association ({}, {}) deleted", group, application);
				} else {
					logger.debug("association ({}, {}) not found", group, application);
				}
			}
			
			group.getApplications().removeAll(applicationsToBeDeleted);
			deletedApplications = applicationsToBeDeleted.size() > 0;
		}
		
		return deletedApplications;
	}

	@Override
	public void addUsers(Group group) {
		if (CollectionUtils.isEmpty(group.getUsers())) {
			logger.debug("group.users is empty");
		} else {
			logger.debug("group.users contain {} users", group.getUsers().size());
			for (User user: group.getUsers()) {
				groupDAO.addUser(group.getGroupId(), user.getUserId());
				logger.debug("association ({}, {}) created", group, user);
			}
		}
	}

	@Override
	public boolean deleteUsers(Group group) {
		boolean deletedUsers = false;
		
		if (CollectionUtils.isEmpty(group.getUsers())) {
			logger.debug("group.users is empty");
		} else if (groupDAO.getGroup(group.getGroupId()) == null) {
			logger.debug("groupId={} not exist", group.getGroupId());
		} else {
			List<User> usersToBeDeleted = new ArrayList<User>();
			
			logger.debug("group.users contain {} Users", group.getUsers().size());
			for (User user: group.getUsers()) {
				if (groupDAO.deleteUser(group.getGroupId(), user.getUserId()) > 0) {
					usersToBeDeleted.add(user);
					logger.debug("association ({}, {}) deleted", group, user);
				} else {
					logger.debug("association ({}, {}) not found", group, user);
				}
			}
			
			group.getUsers().removeAll(usersToBeDeleted);
			deletedUsers = usersToBeDeleted.size() > 0;
		}
		
		return deletedUsers;
	}
	
}
